package com.cc.dy.api.impl;

import com.alibaba.fastjson.JSON;
import com.cc.dy.api.AbstractApiService;
import com.cc.dy.api.DyUserService;
import com.cc.dy.api.response.user.DyMobileResponse;
import com.cc.dy.api.response.user.DyUserInfoResponse;
import com.cc.dy.executer.DyService;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

@Slf4j
public class DyUserServiceImpl extends AbstractApiService implements DyUserService {

    public DyUserServiceImpl(DyService dyService) {
        super(dyService);
    }

    /**
     * 获取手机号码
     *
     * @param sessionKey    开发者通过code2session接口得到的session_key。
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return 手机号码
     */
    @Override
    public DyMobileResponse getMobile(String sessionKey, String encryptedData, String iv) {
        try {
            String mobileInfo = parse(sessionKey, encryptedData, iv);
            return JSON.parseObject(mobileInfo, DyMobileResponse.class);
        } catch (Exception e) {
            log.error("手机号码解析错误: ", e);
            throw new RuntimeException("手机号码解析错误", e);
        }
    }

    /**
     * 获取已登录用户的基本信息或特殊信息，首次使用的用户会弹出授权提示窗，若用户同意，则会返回用户的真实数据。
     *
     * @param sessionKey    开发者通过code2session接口得到的session_key。
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return 用户的基本信息
     */
    @Override
    public DyUserInfoResponse getUserInfo(String sessionKey, String encryptedData, String iv) {
        try {
            String userInfo = parse(sessionKey, encryptedData, iv);
            return JSON.parseObject(userInfo, DyUserInfoResponse.class);
        } catch (Exception e) {
            log.error("用户的基本信息解析错误: ", e);
            throw new RuntimeException("用户的基本信息解析错误", e);
        }
    }

    /**
     * 解密数据
     *
     * @param sessionKey    开发者通过code2session接口得到的session_key。
     * @param encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param iv            加密算法的初始向量
     * @return 数据
     */
    private String parse(String sessionKey, String encryptedData, String iv) {
        try {
            Base64.Decoder decoder = Base64.getDecoder();
            byte[] sessionKeyBytes = decoder.decode(sessionKey);
            byte[] ivBytes = decoder.decode(iv);
            byte[] encryptedBytes = decoder.decode(encryptedData);

            // JDK does not support PKCS7Padding, use PKCS5Padding instead
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
            byte[] ret = cipher.doFinal(encryptedBytes);
            return new String(ret);
        } catch (Exception e) {
            log.error("加密数据解析错误: ", e);
        }
        return null;
    }
}
